package com.glorysoft.sunnypda.base

import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.EXTRA_APP_PACKAGE
import android.view.LayoutInflater
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat.EXTRA_CHANNEL_ID
import androidx.core.app.NotificationManagerCompat
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.lifecycle.lifecycleOwner
import com.glorysoft.hlgdpda.utils.MyUtils
import com.glorysoft.sunnypda.R
import com.gyf.barlibrary.ImmersionBar
import com.pda.platform.ui.ui_pdaplatform.dialog.FreeUI_DownloadFragmentDialog
import com.pda.platform.ui.ui_pdaplatform.entity.FreeUI_VersionEntity
import com.pda.platform.ui.ui_pdaplatform.utils_public.*
import kotlinx.android.synthetic.main.activity_title.*
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type


abstract class BaseActivity<VM : BaseViewModel, DB : ViewDataBinding> : AppCompatActivity(),
    IBaseView {

    protected lateinit var viewModel: VM

    protected lateinit var mBinding: DB

    private var dialog: MaterialDialog? = null

    private var mImmersionBar: ImmersionBar? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        FreeApi_ActivityManager.getActivityManager().addActivity(this)
        initViewDataBinding()
        ImmersionBar.with(this).statusBarDarkFont(true).init()
        //强制竖屏
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        initViewTitle()
        //注册 UI事件
        lifecycle.addObserver(viewModel)
        registerDefUIChange()
        initView(savedInstanceState)
        initData()
        checkNotify()
    }

    override fun onDestroy() {
        super.onDestroy()
        ImmersionBar.with(this).statusBarDarkFont(true).destroy()
        FreeApi_ActivityManager.getActivityManager().finishActivity(this)
    }

    abstract fun layoutId(): Int
    abstract fun initVariableId(): Int
    abstract fun initView(savedInstanceState: Bundle?)
    abstract fun initData()


    /**
     * DataBinding or ViewBinding
     */
    private fun initViewDataBinding() {
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val cls = type.actualTypeArguments[1] as Class<*>
            when {
                ViewDataBinding::class.java.isAssignableFrom(cls) && cls != ViewDataBinding::class.java -> {
                    if (layoutId() == 0) throw IllegalArgumentException("Using DataBinding requires overriding method layoutId")
                    mBinding = DataBindingUtil.setContentView(this, layoutId())
                    (mBinding as ViewDataBinding).lifecycleOwner = this
                }
                ViewBinding::class.java.isAssignableFrom(cls) && cls != ViewBinding::class.java -> {
                    cls.getDeclaredMethod("inflate", LayoutInflater::class.java).let {
                        @Suppress("UNCHECKED_CAST")
                        mBinding = it.invoke(null, layoutInflater) as DB
                        setContentView(mBinding.root)
                    }
                }
                else -> {
                    if (layoutId() == 0) throw IllegalArgumentException("If you don't use ViewBinding, you need to override method layoutId")
                    setContentView(layoutId())
                }
            }
            createViewModel(type.actualTypeArguments[0])
            //关联ViewModel
            mBinding.setVariable(initVariableId(), viewModel)
        } else throw IllegalArgumentException("Generic error")
    }

    /**
     * 注册 UI 事件
     */
    private fun registerDefUIChange() {
        viewModel.defUI.showDialog.observe(this, {
            showLoading()
        })
        viewModel.defUI.dismissDialog.observe(this, {
            dismissLoading()
        })
        viewModel.defUI.toastEvent.observe(this, {
            FreeApi_ToastUtils.showFreeToast(it.message, this, it.isOk, 0)
        })
    }
    /**
     * 打开等待框
     */
    open fun showLoading() {
        (dialog ?: MaterialDialog(this)
            .cancelable(false)
            .cornerRadius(8f)
            .customView(R.layout.free_ui_glory_dialog_loading, noVerticalPadding = false)
            .lifecycleOwner(this)
            .maxWidth(R.dimen.dialog_width).also {
                dialog = it
            })
            .show()

    }

    /**
     * 关闭等待框
     */
    private fun dismissLoading() {
        dialog?.run { if (isShowing) dismiss() }
    }


    /**
     * 创建 ViewModel
     */
    @Suppress("UNCHECKED_CAST")
    fun createViewModel(type: Type) {
        val tClass = type as? Class<VM> ?: BaseViewModel::class.java
        viewModel = ViewModelProvider(viewModelStore, defaultViewModelProviderFactory)
            .get(tClass) as VM
    }

    //
    override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory {
        return MvvmConfig.getConfig().viewModelFactory()
            ?: super.getDefaultViewModelProviderFactory()
    }

    /**
     * 设置标题
     *
     * @param title
     */
    open fun setTitle(title: String) {
        if (tvTitle != null) {
            tvTitle.text = title
        }
    }

    open fun setRightListener(title: String, listener: View.OnClickListener?) {
        if (title.isNotEmpty()) {
            tvRight.visibility = View.VISIBLE
            tvRight.text = title
            tvRight.setOnClickListener(listener)
        } else {
            tvRight.visibility = View.GONE
        }
    }

    open fun setRightListener(resID: Int, listener: View.OnClickListener?) {
        if (resID > 0) {
            ivRight.visibility = View.VISIBLE
            ivRight.setImageResource(resID)
            ivRight.setOnClickListener(listener)
        } else {
            ivRight.visibility = View.GONE
        }
    }

    /**
     * 跳转界面
     *
     * @param c 目标Activity
     */
    open fun startActivity(c: Class<*>?) {
        startActivity(Intent(this, c))
    }

    /**
     * 携带数据跳转界面
     *
     * @param c      目标Activity
     * @param bundle 携带数据
     */
    open fun startActivity(c: Class<*>?, bundle: Bundle?) {
        val intent = Intent(this, c)
        intent.putExtras(bundle!!)
        startActivity(intent)
    }

    override fun initViewTitle() {
        if (ivBack != null) {
            ivBack.setOnClickListener { finish() }
        }

        if (tvCurrentUser != null) {
            tvCurrentUser.text = Constant.CURRENT_USER_NAME
        }

    }

    /**
     * 不获取焦点初始化editText
     * @param editText
     * @param listener
     * @param
     */
    protected open fun initEdit(
        editText: EditText,
        listener: EditTextListener
    ) {
        MyUtils.initEnterToUpperCase(editText)
        FreeApi_EditTextUtils.setEditTextListener(editText, this) { s: String ->
            listener.onTextChangeListener(s)
        }
    }

    override fun initParam() {
    }

    interface EditTextListener {
        fun onTextChangeListener(s: String)
    }

    //通知栏权限
    fun checkNotify() {
        val manager = NotificationManagerCompat.from(this)
        if (!manager.areNotificationsEnabled()) {
            FreeApi_DialogUtils.getConfirmAndCancelDialog(this, "未开启通知权限，是否去开启？", {
                try {
                    val intent = Intent()
                    intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                    intent.putExtra(EXTRA_APP_PACKAGE, packageName)
                    intent.putExtra(EXTRA_CHANNEL_ID, applicationInfo.uid)

                    intent.putExtra("app_package", packageName)
                    intent.putExtra("app_uid", applicationInfo.uid)

                    startActivity(intent)
                } catch (e: Exception) {
                    e.printStackTrace()
                    val intent = Intent()

                    intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                    val uri: Uri = Uri.fromParts("package", packageName, null)
                    intent.data = uri
                    startActivity(intent)
                }
            }) {}.show(supportFragmentManager, "SUBMIT_DIALOG")
        }
    }

}